package no.met.metadataeditor.view;
import java.io.IOException;
import java.util.Iterator;
import java.util.Map;
import java.util.logging.Logger;
import javax.el.ELException;
import javax.faces.FacesException;
import javax.faces.application.ViewExpiredException;
import javax.faces.application.ViewHandler;
import javax.faces.component.UIViewRoot;
import javax.faces.context.ExceptionHandler;
import javax.faces.context.ExternalContext;
import javax.faces.context.FacesContext;
import javax.faces.event.AbortProcessingException;
import javax.faces.event.ExceptionQueuedEvent;
import javax.faces.event.PreRenderViewEvent;
import javax.faces.view.ViewDeclarationLanguage;
import no.met.metadataeditor.EditorException;
import no.met.metadataeditor.LogUtils;
import org.omnifaces.exceptionhandler.FullAjaxExceptionHandler;
/**
* Extend the FullAjaxExceptionHandler with exception handling for non ajax requests.
*/
public class EditorExceptionHandler extends FullAjaxExceptionHandler {
private static final Logger logger = Logger.getLogger(EditorExceptionHandler.class.getName());
private ExceptionHandler wrapped;
public EditorExceptionHandler(ExceptionHandler wrapped) {
super(wrapped);
this.wrapped = wrapped;
}
@Override
public void handle() throws FacesException {
FacesContext context = FacesContext.getCurrentInstance();
if (context == null || !context.getPartialViewContext().isAjaxRequest()) {
handleNonAjaxException(FacesContext.getCurrentInstance());
} else {
super.handle();
}
wrapped.handle();
}
private void handleNonAjaxException(FacesContext context) {
Iterator<ExceptionQueuedEvent> unhandledExceptionQueuedEvents = getUnhandledExceptionQueuedEvents().iterator();
if (unhandledExceptionQueuedEvents.hasNext()) {
Throwable exception = unhandledExceptionQueuedEvents.next().getContext().getException();
if (exception instanceof AbortProcessingException) {
return; // Let JSF handle it itself.
}
// go up the exception chain to the cause
while ((exception instanceof FacesException || exception instanceof ELException )
&& exception.getCause() != null) {
exception = exception.getCause();
}
unhandledExceptionQueuedEvents.remove();
// put information about the exception in the log. For unhandled exceptions
// this should not already have been done.
LogUtils.logException(logger, exception.getMessage(), exception);
String viewName;
if (exception instanceof ViewExpiredException) {
viewName = "/error-pages/view-expired.xhtml";
} else if (exception instanceof EditorException ) {
viewName = "/error-pages/editor-error.xhtml";
} else {
viewName = "/error-pages/server-error.xhtml";
}
ExternalContext externalContext = context.getExternalContext();
Map<String, Object> requestMap = externalContext.getRequestMap();
requestMap.put("exception", exception);
FacesContext facesContext = FacesContext.getCurrentInstance();
try {
ViewHandler viewHandler = context.getApplication().getViewHandler();
UIViewRoot viewRoot = viewHandler.createView(context, viewName);
context.setViewRoot(viewRoot);
context.getPartialViewContext().setRenderAll(true);
ViewDeclarationLanguage vdl = viewHandler.getViewDeclarationLanguage(context, viewName);
vdl.buildView(context, viewRoot);
context.getApplication().publishEvent(context, PreRenderViewEvent.class, viewRoot);
vdl.renderView(context, viewRoot);
context.responseComplete();
} catch (IOException e) {
LogUtils.logException(logger, "Failed to handled exception in non ajax request.", e);
}
facesContext.responseComplete();
}
while (unhandledExceptionQueuedEvents.hasNext()) {
// Any remaining unhandled exceptions are not interesting. First fix
// the first.
unhandledExceptionQueuedEvents.next();
unhandledExceptionQueuedEvents.remove();
}
}
}